#include "music.h"
#include "gd32e23x_it.h"

#define MUSIC_SDA_PORT            GPIOB
#define MUSIC_SDA_PIN             GPIO_PIN_4

#define MUSIC_CLK_PORT            GPIOB
#define MUSIC_CLK_PIN             GPIO_PIN_3

#define MUSIC_BUSY_PORT           GPIOB
#define MUSIC_BUSY_PIN            GPIO_PIN_0

#define MUSIC_CLK_LEVEL_SET       gpio_bit_set(MUSIC_CLK_PORT, MUSIC_CLK_PIN)
#define MUSIC_CLK_LEVEL_RESET       gpio_bit_reset(MUSIC_CLK_PORT, MUSIC_CLK_PIN)
#define MUSIC_SDA_LEVEL_SET       gpio_bit_set(MUSIC_SDA_PORT, MUSIC_SDA_PIN)
#define MUSIC_SDA_LEVEL_RESET       gpio_bit_reset(MUSIC_SDA_PORT, MUSIC_SDA_PIN)
#define MUSIC_BUSY_LEVEL_GET      gpio_input_bit_get(MUSIC_BUSY_PORT, MUSIC_BUSY_PIN)

#define MUSIC_TIMER_ENABLE       timer_enable(TIMER2)
#define MUSIC_TIMER_DISABLE       timer_disable(TIMER2)

static volatile uint16_t music_delay_cnt;
void TIMER2_IRQHandler(void)
{
    if(SET == timer_interrupt_flag_get(TIMER2, TIMER_INT_UP)){
        /* clear channel 0 interrupt bit */
        timer_interrupt_flag_clear(TIMER2, TIMER_INT_UP);
        if(music_delay_cnt!=0)
        music_delay_cnt--;
    }
}

static music_delay_100us(uint16_t n)
{
   music_delay_cnt = n;
   while(music_delay_cnt);
}

static void music_send_one_byte(uint8_t dat)
{
   MUSIC_TIMER_ENABLE;
   MUSIC_CLK_LEVEL_RESET;
   music_delay_100us(40);//>=40ms
   for(uint8_t i=0; i<8; i++)
   {
      if(dat&0x1)
        MUSIC_SDA_LEVEL_SET;
      else
        MUSIC_SDA_LEVEL_RESET;
      MUSIC_CLK_LEVEL_RESET;
      music_delay_100us(6);   //delay 500us at least
      MUSIC_CLK_LEVEL_SET;
      music_delay_100us(6);   //delay 500us at least
      dat>>=1;
   }
   MUSIC_CLK_LEVEL_SET;
   MUSIC_TIMER_DISABLE;
}

void music_set_vol(uint8_t vol)
{
   //vol have 8 level(0-7), 0 is lowest   7 is highest
   music_send_one_byte(0xE0+vol);
}

void music_stop_play(void)
{
   music_send_one_byte(0xFE);
}

void music_cycle_play(void)
{
   music_send_one_byte(0xFE);
}

void music_init(void)
{
   rcu_periph_clock_enable(RCU_GPIOA);
   rcu_periph_clock_enable(RCU_GPIOB);
   gpio_mode_set(MUSIC_SDA_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP, MUSIC_SDA_PIN);
   gpio_output_options_set(MUSIC_SDA_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_10MHZ, MUSIC_SDA_PIN);

   gpio_mode_set(MUSIC_CLK_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP, MUSIC_CLK_PIN);
   gpio_output_options_set(MUSIC_CLK_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_10MHZ, MUSIC_CLK_PIN);

   gpio_mode_set(MUSIC_BUSY_PORT, GPIO_MODE_INPUT, GPIO_PUPD_PULLUP, MUSIC_BUSY_PIN);

   timer_parameter_struct timer_initpara;

   rcu_periph_clock_enable(RCU_TIMER2);
   timer_deinit(TIMER2);
   /* TIMER2 configuration */
    timer_initpara.prescaler         = 71;
    timer_initpara.alignedmode       = TIMER_COUNTER_EDGE;
    timer_initpara.counterdirection  = TIMER_COUNTER_UP;
    timer_initpara.period            = 100;
    timer_initpara.clockdivision     = TIMER_CKDIV_DIV1;
    timer_initpara.repetitioncounter = 0;
    timer_init(TIMER2,&timer_initpara);

    /* auto-reload preload enable */
    timer_auto_reload_shadow_enable(TIMER2);
    timer_interrupt_enable(TIMER2, TIMER_INT_UP);
    nvic_irq_enable(TIMER2_IRQn, 3);
    timer_enable(TIMER2);
}


